#include <stdio.h>
#include <pcap.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>

/* 定义文件指针 */
FILE *output_file;

/* 数据包处理回调函数 */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
    struct ip *ip_hdr;
    struct tcphdr *tcp_hdr;
    int ip_header_length;

    /* 计算 IP 头部的长度 */
    ip_hdr = (struct ip *)(pkt_data + 14); // 跳过以太网头部
    ip_header_length = ip_hdr->ip_hl * 4;

    /* 检查是否为 TCP 数据包 */
    if (ip_hdr->ip_p == IPPROTO_TCP)
    {
        tcp_hdr = (struct tcphdr *)(pkt_data + 14 + ip_header_length);

        /* 检查是否为 SYN 包（TCP 连接建立的标志） */
        if (tcp_hdr->th_flags & TH_SYN)
        {
            /* 打印到终端 */
            printf("TCP 连接建立数据包\n");
            printf("源端口: %u\n", ntohs(tcp_hdr->th_sport));
            printf("目的端口: %u\n", ntohs(tcp_hdr->th_dport));

            /* 保存到文件 */
            fprintf(output_file, "TCP 连接建立数据包\n");
            fprintf(output_file, "源端口: %u\n", ntohs(tcp_hdr->th_sport));
            fprintf(output_file, "目的端口: %u\n", ntohs(tcp_hdr->th_dport));
            fflush(output_file); // 刷新缓冲区，确保数据及时写入文件
        }
    }
}

int main()
{
    pcap_t *handle;
    char errbuf[PCAP_ERRBUF_SIZE];
    struct bpf_program fp;
    char filter_exp[] = "tcp";
    bpf_u_int32 net;

    /* 打开输出文件 */
    output_file = fopen("tcp_captured_data.txt", "w");
    if (output_file == NULL)
    {
        fprintf(stderr, "无法打开输出文件\n");
        return 1;
    }

    /* 打开默认网络设备 */
    handle = pcap_open_live(pcap_lookupdev(errbuf), BUFSIZ, 1, 1000, errbuf);
    if (handle == NULL)
    {
        fprintf(stderr, "无法打开设备: %s\n", errbuf);
        fclose(output_file);
        return 2;
    }

    /* 编译过滤规则 */
    if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1)
    {
        fprintf(stderr, "无法编译过滤规则: %s\n", pcap_geterr(handle));
        fclose(output_file);
        pcap_close(handle);
        return 2;
    }

    /* 应用过滤规则 */
    if (pcap_setfilter(handle, &fp) == -1)
    {
        fprintf(stderr, "无法应用过滤规则: %s\n", pcap_geterr(handle));
        fclose(output_file);
        pcap_close(handle);
        return 2;
    }

    /* 开始捕获数据包 */
    pcap_loop(handle, 0, packet_handler, NULL);

    /* 关闭设备和文件 */
    pcap_close(handle);
    fclose(output_file);
    return 0;
}
